#include "qserverupdate.h"

#include "../qdeviceserver.h"
#include "../qbasedefine.h"

#include <math.h>

QServerUpdate::QServerUpdate(QDeviceServer *server, QObject *parent):
    QObject(parent),
    m_device_server(server),
    m_failed_times(0),
    m_timer(new QTimer)
{
    connect(m_timer,SIGNAL(timeout()),this,SLOT(timer()));
    connect(m_device_server,SIGNAL(recv_data(QByteArray)),this,SLOT(recv(QByteArray)));
}

QServerUpdate::~QServerUpdate()
{
    delete m_timer;
}

int QServerUpdate::update(const QByteArray &data, tagDeviceInfo *info)
{
    clear();
    m_device_info=*info;

    int pt=0;
    QByteArray array;
    uint sum;
    while(pt<data.size())
    {
        sum=0;
        array=data.mid(pt,qMin(data.size()-pt,1020));
        pt+=array.size();
        for(int i=0;i<array.size();i++)
        {
            sum+=(array.at(i)&0xff);
        }
        array.append((sum>>24)&0xff);
        array.append((sum>>16)&0xff);
        array.append((sum>>8)&0xff);
        array.append(sum&0xff);
        m_send_data.append(array);
    }

    if(m_send_data.size()>0)
    {
        QByteArray array=QString::number(UPDATE_CONTROL_CODE).toLocal8Bit()
                +QByteArray(":")+m_device_server->get_server_info()->m_uuid.toLocal8Bit()
                +":"+m_device_info.m_uuid.toLocal8Bit()+QByteArray(":Start");
        m_device_server->send_data(array,m_device_info.m_device_ip);
        m_last_time=QDateTime::currentDateTime();
        m_timer->start(30);
        m_failed_times=0;
        m_is_updating=true;
        m_position=-1;
    }
    else
    {
        clear();
        emit success();
    }
    return m_send_data.size();
}

void QServerUpdate::clear()
{
    m_position=-1;
    m_device_info.m_uuid="";
    m_send_data.clear();
    m_failed_times=0;
    m_timer->stop();
}

void QServerUpdate::timer()
{
    if(m_device_info.m_uuid=="")
    {
        return;
    }
    QDateTime dt=QDateTime::currentDateTime();

    if(m_failed_times>3)
    {
        clear();
        emit offline();
        return;
    }
    if(m_last_time.msecsTo(dt)>1000)
    {
        if(m_position>=0)
        {
            QByteArray array=QString::number(UPDATE_CONTROL_CODE).toLocal8Bit()
                    +QByteArray(":")+m_device_server->get_server_info()->m_uuid.toLocal8Bit()
                    +":"+m_device_info.m_uuid.toLocal8Bit()
                    +QByteArray(":")+m_send_data.first();
            m_device_server->send_data(array,m_device_info.m_device_ip);
            m_last_time=QDateTime::currentDateTime();
            m_failed_times++;
        }
        else
        {
            QByteArray array=QString::number(UPDATE_CONTROL_CODE).toLocal8Bit()
                    +QByteArray(":")+m_device_server->get_server_info()->m_uuid.toLocal8Bit()
                    +":"+m_device_info.m_uuid.toLocal8Bit()+QByteArray(":Start");
            m_device_server->send_data(array,m_device_info.m_device_ip);
            m_last_time=QDateTime::currentDateTime();
            m_failed_times++;
        }
    }
}

void QServerUpdate::recv(const QByteArray &data)
{
    if(!m_is_updating)
    {
        return;
    }
    QString str=QString(data);

    int index=str.indexOf(":");
    if(index<=0)
    {
        return;
    }
    int code=str.left(index).toInt();
    QString value=str.mid(index+1);

    if(code!=UPDATE_CONTROL_CODE)
    {
        return;
    }

    index=value.indexOf(":");
    if(index<=0)
    {
        return;
    }
    QString server_uuid=value.left(index);
    value=value.mid(index+1);
    index=value.indexOf(":");
    QString client_uuid=value.left(index);
    if(client_uuid!=m_device_info.m_uuid || server_uuid!=m_device_server->get_server_info()->m_uuid)
    {
        return;
    }
    value=value.mid(index+1);
    if(value=="Ok")
    {
        m_send_data.removeFirst();
        if(m_send_data.size()==0)
        {
            str=QString::number(UPDATE_CONTROL_CODE)+":"+server_uuid+":"
                    +client_uuid+":Done";
            m_device_server->send_data(str.toLocal8Bit(),m_device_info.m_device_ip);
            m_last_time=QDateTime::currentDateTime();
            m_failed_times=0;
        }
        else
        {
            QByteArray array=QString::number(UPDATE_CONTROL_CODE).toLocal8Bit()
                    +QByteArray(":")+server_uuid.toLocal8Bit()
                    +QByteArray(":")+client_uuid.toLocal8Bit()+QByteArray(":")+m_send_data.first();
            m_device_server->send_data(array,m_device_info.m_device_ip);
            m_last_time=QDateTime::currentDateTime();
            m_failed_times=0;
        }
        m_position++;
        emit position(m_position);
    }
    else if(value=="Done")
    {
        clear();
        emit success();
    }
    else if(value=="Busy")
    {
        clear();
        emit failed();
    }
    else if(value=="Start")
    {
        QByteArray array=QString::number(UPDATE_CONTROL_CODE).toLocal8Bit()
                +QByteArray(":")+server_uuid.toLocal8Bit()
                +QByteArray(":")+client_uuid.toLocal8Bit()
                +QByteArray(":")+m_send_data.first();
        m_device_server->send_data(array,m_device_info.m_device_ip);
        m_last_time=QDateTime::currentDateTime();
        m_failed_times=0;
        m_position=0;
        emit position(m_position);
    }
    else if(value=="Done Failed")
    {
        clear();
        emit failed();
    }
    else
    {
        if(m_failed_times>3)
        {
            clear();
            emit failed();
        }
        else
        {
            QByteArray array=QString::number(UPDATE_CONTROL_CODE).toLocal8Bit()
                    +QByteArray(":")+server_uuid.toLocal8Bit()
                    +QByteArray(":")+client_uuid.toLocal8Bit()+QByteArray(":")+m_send_data.first();
            m_device_server->send_data(array,m_device_info.m_device_ip);
            m_last_time=QDateTime::currentDateTime();
            m_failed_times++;
        }
    }
}
